package pe.gob.mininter.dirandro.vaadin.panel.mantenimiento;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import pe.gob.mininter.dirandro.model.Delito;
import pe.gob.mininter.dirandro.model.Opcion;
import pe.gob.mininter.dirandro.model.Valor;
import pe.gob.mininter.dirandro.service.DelitoService;
import pe.gob.mininter.dirandro.service.ValorService;
import pe.gob.mininter.dirandro.util.Constante;
import pe.gob.mininter.dirandro.vaadin.dialogs.AlertDialog;
import pe.gob.mininter.dirandro.vaadin.util.DirandroComponent;
import pe.gob.mininter.dirandro.vaadin.util.Injector;

import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.event.ShortcutListener;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.TreeTable;
import com.vaadin.ui.VerticalLayout;

public class PanelMantenDelito extends DirandroComponent implements ClickListener, TextChangeListener {

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */
	
	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private HorizontalLayout pnlDelitoContenido;
	@AutoGenerated
	private VerticalLayout pnlDatosDelito;
	@AutoGenerated
	private HorizontalLayout pnlFila5;
	@AutoGenerated
	private Button btnEliminarDelito;
	@AutoGenerated
	private Button btnCrearDelito;
	@AutoGenerated
	private TextArea txaObservacion;
	@AutoGenerated
	private HorizontalLayout pnlFila4;
	@AutoGenerated
	private ComboBox cmbTipoProcesalDelito;
	@AutoGenerated
	private ComboBox cmbEstadoDelito;
	@AutoGenerated
	private ComboBox cmbPadreDelito;
	@AutoGenerated
	private TextField txtNombreDelito;
	@AutoGenerated
	private Label lblGrabarDelito;
	@AutoGenerated
	private VerticalLayout pnlListadoDelito;
	@AutoGenerated
	private TreeTable treeDelitos;
	@AutoGenerated
	private TextField txtFitroDelitoNombre;
	@AutoGenerated
	private Label lblFiltro;
	private static final long serialVersionUID = -1422634865081573120L;
	
	private DelitoService delitoService;	
	private ValorService valorService;
	
	private List<Delito> lstDelitos;
	private List<Valor> lstEstados;
	private List<Valor> lstTipoProcesales;
	private boolean flagNuevoDelito;
	private Long idDelito;
	
	public PanelMantenDelito(List<Opcion> acciones,String height){
		super(acciones, height);		
		delitoService = Injector.obtenerServicio(DelitoService.class);
		valorService = Injector.obtenerServicio(ValorService.class);
		buildMainLayout();
		setCompositionRoot(mainLayout);
		postConstruct();
	}
	
	@Override
	public void postConstruct() {
			    
		flagNuevoDelito = true;
		
	    txtNombreDelito.setInputPrompt("Nombre");
	    txtFitroDelitoNombre.setInputPrompt("Delito");
	    txtFitroDelitoNombre.setImmediate(true);
	    txtFitroDelitoNombre.addShortcutListener(new ShortcutListener("", KeyCode.ENTER, null) {
			
			private static final long serialVersionUID = 4068232062569621771L;

			@Override
			public void handleAction(Object sender, Object target) {
				shortCutEnter(sender, target);
			}
		});
		
		treeDelitos.setSelectable(true);
		treeDelitos.setImmediate(true);
		
		btnEliminarDelito.setIcon(Constante.ICONOS.DELETE);
		btnEliminarDelito.addListener((ClickListener)this);
		btnEliminarDelito.setVisible(false);
		
		btnCrearDelito.setIcon(Constante.ICONOS.SAVE);
		btnCrearDelito.addListener((ClickListener)this);
		btnCrearDelito.setCaption("Crear");
		
		cmbPadreDelito.setInputPrompt("Padre");
		cmbPadreDelito.setItemCaptionPropertyId("nombre");
		
		treeDelitos.setCacheRate(1);
		treeDelitos.addListener(new Property.ValueChangeListener() {

			private static final long serialVersionUID = 646406512747295285L;
			
			@Override
			public void valueChange(ValueChangeEvent event) {
				boolean esModoNuevo = treeDelitos.getValue() == null;
				limpiar();
				if (esModoNuevo) {
					treeDelitos.setValue(null);
					habilitarEdicion(!esModoNuevo);
				}else{
					Item item = treeDelitos.getItem(treeDelitos.getValue());
					idDelito = (Long) item.getItemProperty("id") .getValue();
					txtNombreDelito.setValue(item.getItemProperty("nombre").getValue());
					txaObservacion.setValue(item.getItemProperty("observacion").getValue());
					cmbEstadoDelito.select(new Valor((Long) item.getItemProperty("estado.id").getValue()));
					cmbPadreDelito.select((Delito) item.getItemProperty("padre").getValue());
					cmbEstadoDelito.select(new Valor((Long) item.getItemProperty("estado.id").getValue()));
					cmbTipoProcesalDelito.select(new Valor((Long) item.getItemProperty("codigoProcesal.id").getValue()));
					habilitarEdicion(!esModoNuevo);
				}
			}			
		});

	    cargarDelitosCombo();
	    cargarEstadosDelito();
	    cargarTipoProcesalDelito();
	    refrescar();
	}
	
	private void habilitarEdicion(boolean flag) {
		flagNuevoDelito = !flag;
		btnEliminarDelito.setVisible(flag);
		
		if(flag)
			btnCrearDelito.setCaption("Actualizar");
		else
			btnCrearDelito.setCaption("Crear");
	}
	
	private void cargarDelitosCombo(){
		lstDelitos = delitoService.buscar(null);
		cmbPadreDelito.setContainerDataSource(new BeanItemContainer<Delito>(Delito.class, lstDelitos));
		cmbPadreDelito.setItemCaptionPropertyId("nombre");
	}
	
	private void cargarEstadosDelito(){
		lstEstados = valorService.obtenerLista(Constante.LISTA.CODIGO.ESTADO);
		cmbEstadoDelito.setInputPrompt("Estado");
		cmbEstadoDelito.setContainerDataSource(new BeanItemContainer<Valor>(Valor.class,  lstEstados));
		cmbEstadoDelito.setItemCaptionPropertyId("nombre");
	}
	
	private void cargarTipoProcesalDelito(){
		lstTipoProcesales = valorService.obtenerLista(Constante.LISTA.CODIGO.COD_PROCESAL);
		cmbTipoProcesalDelito.setInputPrompt("Codigo Procesal");
		cmbTipoProcesalDelito.setContainerDataSource(new BeanItemContainer<Valor>(Valor.class,  lstTipoProcesales));
		cmbTipoProcesalDelito.setItemCaptionPropertyId("nombre");
	}
	
	private void cargarDelitos(Map<String,List<Delito>> map){
		
		HierarchicalContainer hwContainer = new HierarchicalContainer();

		hwContainer.addContainerProperty("id", Long.class, 0L);
		hwContainer.addContainerProperty("nombre", String.class, "");
		hwContainer.addContainerProperty("estado", Valor.class, null);
		hwContainer.addContainerProperty("estado.id", Long.class, null);
		hwContainer.addContainerProperty("padre", Delito.class, null);
		hwContainer.addContainerProperty("padre.id", Long.class, null);		
		hwContainer.addContainerProperty("codigoProcesal", Valor.class, null);
		hwContainer.addContainerProperty("codigoProcesal.id", Long.class, null);
		hwContainer.addContainerProperty("observacion", String.class, "");
		
		if(map.get(Constante.OPCION.KEY_PADRE) != null){
			recorrer(Constante.OPCION.KEY_PADRE, map, null, hwContainer);
		}
		treeDelitos.setContainerDataSource(hwContainer);		
		treeDelitos.setItemCaptionPropertyId("nombre");
		
		treeDelitos.setVisibleColumns(new Object[]{"nombre"});
		
		for (Object id : treeDelitos.rootItemIds()) 
			treeDelitos.setCollapsed(id, false);
		
		for (Object itemId: treeDelitos.getItemIds())
			treeDelitos.setCollapsed(itemId, false);
		
		treeDelitos.setPageLength(treeDelitos.size());
	}	

	private void recorrer(String nombre, Map<String, List<Delito>> map, Long objPadre, HierarchicalContainer hwContainer) {
		Item item = null;
		for (Delito delito : map.get(nombre)) {
			
			item = hwContainer.addItem(delito.getId());
			item.getItemProperty("id").setValue(delito.getId());
			item.getItemProperty("nombre").setValue(delito.getNombre());
			item.getItemProperty("estado").setValue(delito.getEstado() == null ? null : delito.getEstado());
			item.getItemProperty("estado.id").setValue(delito.getEstado() == null ? null: delito.getEstado().getId());
			item.getItemProperty("codigoProcesal").setValue(delito.getCodigoProcesal() == null ? null : delito.getCodigoProcesal());
			item.getItemProperty("codigoProcesal.id").setValue(delito.getCodigoProcesal() == null ? null: delito.getCodigoProcesal().getId());
			item.getItemProperty("padre").setValue(delito.getPadre() == null ? null : delito.getPadre());
			item.getItemProperty("padre.id").setValue(delito.getPadre() == null ? null: delito.getPadre().getId());
			item.getItemProperty("observacion").setValue(delito.getObservacion() != null ? delito.getObservacion() : StringUtils.EMPTY);
			
			if (!nombre.equals(Constante.OPCION.KEY_PADRE)) {
				hwContainer.setParent(delito.getId(), objPadre);
			}
			if (map.get(delito.getId().toString()) != null) {
				recorrer(delito.getId().toString(), map, delito.getId(),hwContainer);
			} else {
				hwContainer.setChildrenAllowed(delito.getId().toString(), false);
			}
		}
	}
	
	@Override
	public void buttonClick(ClickEvent event) {
		
		if(event.getSource().equals(btnCrearDelito)){
			StringBuilder sbContenido = new StringBuilder();
			Delito delito = new Delito();
			delito.setNombre((String)txtNombreDelito.getValue());
			delito.setPadre((Delito)cmbPadreDelito.getValue());
			delito.setEstado((Valor)cmbEstadoDelito.getValue());
			delito.setObservacion(txaObservacion.getValue() != null ? txaObservacion.getValue().toString() : StringUtils.EMPTY);
			delito.setCodigoProcesal((Valor)cmbTipoProcesalDelito.getValue());
			
			if (flagNuevoDelito) {
				delitoService.crear(delito);
				sbContenido.append("Delito : ").append(delito.getNombre()).append(" se ha "+ Constante.OPERACION.CREAR_REGISTRO+" satisfactoriamente.");				
			}else {
				delito.setId(idDelito);
				delitoService.actualizar(delito);
				sbContenido.append("Delito : ").append(delito.getNombre()).append(" se ha "+ Constante.OPERACION.ACTUALIZAR_REGISTRO+" satisfactoriamente.");
			}
			
			AlertDialog alertDialog = new  AlertDialog("Delito", sbContenido.toString(), "Aceptar", "400");
			getApplication().getMainWindow().addWindow(alertDialog);
			
		}else{
			if(event.getSource().equals(btnEliminarDelito)){
				delitoService.eliminarXId(idDelito);
			}
		}
		refrescar();
	}
	
	private void refrescar(){
		habilitarEdicion(false);
		cargarDelitosCombo();
		limpiar();
		Map<String,List<Delito>> map = delitoService.listarDelitos();
		cargarDelitos(map);
		
	}
	
	@Override
	public void textChange(TextChangeEvent event) {
		Delito delito = new Delito();
		
		if(event.getSource().equals(txtFitroDelitoNombre)){
			if(StringUtils.isNotBlank(event.getText())){
				delito.setNombre(event.getText());
				List<Delito> delitos = delitoService.buscarPadreHijos(delito);			
				Map<String,List<Delito>> map = delitoService.filtrarDelitos(delitos);
				cargarDelitos(map);
			}else {
				Map<String,List<Delito>> map = delitoService.filtrarDelitos(delitoService.buscar(delito));
				cargarDelitos(map);
			}
		}
	}
	
	private void shortCutEnter(Object sender, Object target){
		Delito delito = null;
		List<Delito> lstDelitos = new ArrayList<Delito>();
		
		if (StringUtils.isNotBlank(target.toString())) {
			if(txtFitroDelitoNombre.equals(target)){
				delito = new Delito();
				if(StringUtils.isNotBlank(txtFitroDelitoNombre.getValue().toString())){
					delito.setNombre(txtFitroDelitoNombre.getValue().toString());
				}
				lstDelitos = delitoService.buscarPadreHijos(delito);
				Map<String,List<Delito>> map = delitoService.filtrarDelitos(lstDelitos);
				cargarDelitos(map);
			}
		}else {
			refrescar();
		}
	}
	
	//** Utilitarios **//
	private void limpiar(){
		txtNombreDelito.setValue("");
		txtFitroDelitoNombre.setValue("");
		txaObservacion.setValue("");
		cmbEstadoDelito.select(null);
		cmbPadreDelito.select(null);	
		cmbTipoProcesalDelito.select(null);
		idDelito = null;
	}

	@AutoGenerated
	private VerticalLayout buildMainLayout() {
		// common part: create layout
		mainLayout = new VerticalLayout();
		mainLayout.setImmediate(false);
		mainLayout.setWidth("100%");
		mainLayout.setHeight("-1px");
		mainLayout.setMargin(true);
		
		// top-level component properties
		setWidth("100.0%");
		setHeight("-1px");
		
		// pnlDelitoContenido
		pnlDelitoContenido = buildPnlDelitoContenido();
		mainLayout.addComponent(pnlDelitoContenido);
		mainLayout.setComponentAlignment(pnlDelitoContenido, new Alignment(20));
		
		return mainLayout;
	}

	@AutoGenerated
	private HorizontalLayout buildPnlDelitoContenido() {
		// common part: create layout
		pnlDelitoContenido = new HorizontalLayout();
		pnlDelitoContenido.setStyleName("whiteBackGround");
		pnlDelitoContenido.setImmediate(false);
		pnlDelitoContenido.setWidth("-1px");
		pnlDelitoContenido.setHeight("-1px");
		pnlDelitoContenido.setMargin(true);
		pnlDelitoContenido.setSpacing(true);
		
		// pnlListadoDelito
		pnlListadoDelito = buildPnlListadoDelito();
		pnlDelitoContenido.addComponent(pnlListadoDelito);
		
		// pnlDatosDelito
		pnlDatosDelito = buildPnlDatosDelito();
		pnlDelitoContenido.addComponent(pnlDatosDelito);
		
		return pnlDelitoContenido;
	}

	@AutoGenerated
	private VerticalLayout buildPnlListadoDelito() {
		// common part: create layout
		pnlListadoDelito = new VerticalLayout();
		pnlListadoDelito.setImmediate(false);
		pnlListadoDelito.setWidth("-1px");
		pnlListadoDelito.setHeight("-1px");
		pnlListadoDelito.setMargin(false);
		
		// lblFiltro
		lblFiltro = new Label();
		lblFiltro.setStyleName("h2");
		lblFiltro.setImmediate(false);
		lblFiltro.setWidth("-1px");
		lblFiltro.setHeight("-1px");
		lblFiltro.setValue("Filtro de Delitos");
		pnlListadoDelito.addComponent(lblFiltro);
		
		// txtFitroDelitoNombre
		txtFitroDelitoNombre = new TextField();
		txtFitroDelitoNombre.setImmediate(false);
		txtFitroDelitoNombre.setWidth("515px");
		txtFitroDelitoNombre.setHeight("-1px");
		pnlListadoDelito.addComponent(txtFitroDelitoNombre);
		
		// treeDelitos
		treeDelitos = new TreeTable();
		treeDelitos.setImmediate(false);
		treeDelitos.setWidth("500px");
		treeDelitos.setHeight("300px");
		pnlListadoDelito.addComponent(treeDelitos);
		
		return pnlListadoDelito;
	}

	@AutoGenerated
	private VerticalLayout buildPnlDatosDelito() {
		// common part: create layout
		pnlDatosDelito = new VerticalLayout();
		pnlDatosDelito.setImmediate(false);
		pnlDatosDelito.setWidth("-1px");
		pnlDatosDelito.setHeight("-1px");
		pnlDatosDelito.setMargin(false);
		pnlDatosDelito.setSpacing(true);
		
		// lblGrabarDelito
		lblGrabarDelito = new Label();
		lblGrabarDelito.setStyleName("h2");
		lblGrabarDelito.setImmediate(false);
		lblGrabarDelito.setWidth("-1px");
		lblGrabarDelito.setHeight("-1px");
		lblGrabarDelito.setValue("Administración de Delitos ");
		pnlDatosDelito.addComponent(lblGrabarDelito);
		
		// txtNombreDelito
		txtNombreDelito = new TextField();
		txtNombreDelito.setCaption("Nombre");
		txtNombreDelito.setImmediate(false);
		txtNombreDelito.setWidth("300px");
		txtNombreDelito.setHeight("-1px");
		txtNombreDelito.setRequired(true);
		txtNombreDelito.setInputPrompt("Nombre del Delito ");
		pnlDatosDelito.addComponent(txtNombreDelito);
		
		// cmbPadreDelito
		cmbPadreDelito = new ComboBox();
		cmbPadreDelito.setCaption("Nivel Superior");
		cmbPadreDelito.setImmediate(false);
		cmbPadreDelito.setWidth("300px");
		cmbPadreDelito.setHeight("-1px");
		cmbPadreDelito.setRequired(true);
		pnlDatosDelito.addComponent(cmbPadreDelito);
		
		// pnlFila4
		pnlFila4 = buildPnlFila4();
		pnlDatosDelito.addComponent(pnlFila4);
		
		// txaObservacion
		txaObservacion = new TextArea();
		txaObservacion.setCaption("Observación");
		txaObservacion.setImmediate(false);
		txaObservacion.setWidth("320px");
		txaObservacion.setHeight("140px");
		pnlDatosDelito.addComponent(txaObservacion);
		
		// pnlFila5
		pnlFila5 = buildPnlFila5();
		pnlDatosDelito.addComponent(pnlFila5);
		pnlDatosDelito.setComponentAlignment(pnlFila5, new Alignment(20));
		
		return pnlDatosDelito;
	}

	@AutoGenerated
	private HorizontalLayout buildPnlFila4() {
		// common part: create layout
		pnlFila4 = new HorizontalLayout();
		pnlFila4.setImmediate(false);
		pnlFila4.setWidth("-1px");
		pnlFila4.setHeight("-1px");
		pnlFila4.setMargin(false);
		pnlFila4.setSpacing(true);
		
		// cmbEstadoDelito
		cmbEstadoDelito = new ComboBox();
		cmbEstadoDelito.setCaption("Estado");
		cmbEstadoDelito.setImmediate(false);
		cmbEstadoDelito.setWidth("-1px");
		cmbEstadoDelito.setHeight("-1px");
		cmbEstadoDelito.setRequired(true);
		pnlFila4.addComponent(cmbEstadoDelito);
		
		// cmbTipoProcesalDelito
		cmbTipoProcesalDelito = new ComboBox();
		cmbTipoProcesalDelito.setCaption("Tipo Proceso");
		cmbTipoProcesalDelito.setImmediate(false);
		cmbTipoProcesalDelito.setWidth("-1px");
		cmbTipoProcesalDelito.setHeight("-1px");
		cmbTipoProcesalDelito.setRequired(true);
		pnlFila4.addComponent(cmbTipoProcesalDelito);
		
		return pnlFila4;
	}

	@AutoGenerated
	private HorizontalLayout buildPnlFila5() {
		// common part: create layout
		pnlFila5 = new HorizontalLayout();
		pnlFila5.setImmediate(false);
		pnlFila5.setWidth("-1px");
		pnlFila5.setHeight("-1px");
		pnlFila5.setMargin(true);
		pnlFila5.setSpacing(true);
		
		// btnCrearDelito
		btnCrearDelito = new Button();
		btnCrearDelito.setCaption("Actualizar");
		btnCrearDelito.setImmediate(true);
		btnCrearDelito.setWidth("-1px");
		btnCrearDelito.setHeight("-1px");
		pnlFila5.addComponent(btnCrearDelito);
		pnlFila5.setComponentAlignment(btnCrearDelito, new Alignment(20));
		
		// btnEliminarDelito
		btnEliminarDelito = new Button();
		btnEliminarDelito.setCaption("Eliminar");
		btnEliminarDelito.setImmediate(true);
		btnEliminarDelito.setWidth("-1px");
		btnEliminarDelito.setHeight("-1px");
		pnlFila5.addComponent(btnEliminarDelito);
		pnlFila5.setComponentAlignment(btnEliminarDelito, new Alignment(20));
		
		return pnlFila5;
	}
	
}